package game.square;

import game.dungeon.position.Direction;
import game.square.temperature.TemperatureScale;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class TransparentSquare extends TeleportationSquare {

	/**
	 * Initialize this new transparent square.
	 *
	 * @param	temperature
	 *          The temperature for this new transparent square.
	 * @param	temperatureScale
	 * 			The temperature scale in which the given temperature
	 * 			is expressed.
	 * @param 	humidity
	 * 			The humidity for this new transparent square.
	 * @param	slipperyMaterial
	 * 			Indicates if this new transparent square is made of a slippery material.
	 * @param	borderDirections
	 * 			The directions to set borders.
	 * @param	teleportationDestinations
	 * 			The teleportation destinations for this square.
	 * @pre		..
	 * 		  | teleportationDestinations != null
	 * @pre		..
	 * 		  | areValidTeleportationDestinations(teleportationDestinations)
	 * @pre		..
	 * 		  | temperatureScale != null
	 * @pre		..
	 * 		  | humidity != null
	 * @pre		..
	 * 		  | borderDirections != null && borderDirections.size() >= 1
	 * @effect	..
	 * 		  | super (temperature, temperatureScale, humidity, slipperyMaterial, teleportationDestinations)
	 * @post	If the given border directions at least contain one effective 
	 * 			direction, than this new transparent square has a door for each direction in 
	 * 			the set.
	 * 		  |	if (for some direction in Direction : borderDirections.contains(direction))
	 * 		  |		than for each direction in borderDirections
	 * 		  |			new.getBorderInDirection(direction).getClass() == Door.class
	 * @post	Else, this new transparent square has a door in the north.
	 * 		  |	else new.getBorderInDirection(Direction.NORTH) == Door.class
	 * @note 	The given temperature scale must correspond to the given
	 * 			temperature.
	 */
	public TransparentSquare(int temperature,
			TemperatureScale temperatureScale, BigDecimal humidity,
			boolean slipperyMaterial, Set<Direction> borderDirections, List<Square> teleportationDestinations) {
		super(temperature, temperatureScale, humidity, slipperyMaterial,
				teleportationDestinations);
		assert (borderDirections != null && borderDirections.size() >= 1);
		placeBorders(borderDirections);
	}
	
	private void placeBorders(Set<Direction> borderDirections){
		Iterator<Direction> it = borderDirections.iterator();
		Direction directionFirstDoor = it.next();
		addBorderInDirection(new Door(), directionFirstDoor);
		int nbOfDoors = 1;
		while (nbOfDoors < 2 && it.hasNext()){
			Direction newDoorDirection = it.next();
			if (directionFirstDoor.getOppositeDirection() == newDoorDirection){
				addBorderInDirection(new Door(), newDoorDirection);
				nbOfDoors ++;
			}
		}
	}

	/**
	 * Check whether this transparent square can have the given border
	 * as one of its borders.
	 * 
	 * @param   border
	 *          The border to check.
	 * @return  ..
	 * 		  | if (!super.canHaveAsBorderInDirection(border, direction))
	 * 		  |		then result == false
	 * @result	Otherwise, if the given border is an instance of Wall
	 * 			than the result is false
	 * 		  | else if (border instanceof Wall)
	 * 		  |		then result == false
	 * @result	Otherwise the result is true.
	 */
	@Override
	public boolean canHaveAsBorderInDirection(Border border, Direction direction) {
		if (!super.canHaveAsBorderInDirection(border, direction))
			return false;
		if (border instanceof Wall)
			return false;
		return true;
	}

	/**
	 * Check if this transparent square has proper borders.
	 * 
	 * @return	..
	 * 		  | if (!super.hasProperBorders())
	 *		  |		then result == false
	 * @result	Otherwise, false if this transparent square has
	 * 			at least one wall.
	 * @result	Otherwise, true if this transparent square has
	 * 			only one door.
	 * @result	Otherwise, false if this transparent square
	 * 			has more than two doors.
	 * @result	Otherwise, true if and only if the doors of this
	 * 			square are located in opposite directions.
	 */
	@Override
	public boolean hasProperBorders() {
		if (!super.hasProperBorders())
			return false;
		List<Direction> doorDirections = new ArrayList<Direction>();
		for (Direction direction : Direction.values()){
			Border border = getBorderInDirection(direction);
			if (border instanceof Wall)
				return false;
			if (border != null && border instanceof Door){
				doorDirections.add(direction);
			}	
		}
		return checkDoors(doorDirections);
	}

	private boolean checkDoors(List<Direction> doorDirections) {
		if (doorDirections.size() == 1 )
			return true;
		if (doorDirections.size() == 2)
			return doorDirections.get(0).getOppositeDirection() == doorDirections.get(1);
		return false;
	}
}
